#ifndef CPUSIMULATOR_H
#define CPUSIMULATOR_H

#include <QObject>
#include <QMap>
#include <QStringList>
#include <QMutex>
#include <QSet>
#include <QTimer>

// 前向声明
class InterruptManager;

/**
 * @brief CPU标志位枚举
 */
enum class CpuFlags {
    Zero = 0x01,        // 零标志位
    Carry = 0x02,       // 进位标志位
    Sign = 0x04,        // 符号标志位
    Overflow = 0x08,    // 溢出标志位
    Parity = 0x10,      // 奇偶校验标志位
    Auxiliary = 0x20,   // 辅助进位标志位
    Interrupt = 0x40,   // 中断标志位
    Direction = 0x80    // 方向标志位
};

/**
 * @brief CPU执行状态枚举
 */
enum class CpuState {
    Stopped,    // 停止状态
    Running,    // 运行状态
    Paused,     // 暂停状态
    Error,      // 错误状态
    Halted      // 停机状态
};

/**
 * @brief 指令类型枚举
 */
enum class InstructionType {
    DataTransfer,   // 数据传输指令
    Arithmetic,     // 算术运算指令
    Logic,          // 逻辑运算指令
    Control,        // 控制转移指令
    Stack,          // 栈操作指令
    Interrupt,      // 中断指令
    Other           // 其他指令
};

/**
 * @brief 指令结构体
 */
struct Instruction {
    QString mnemonic;           // 助记符
    QStringList operands;       // 操作数列表
    InstructionType type;       // 指令类型
    int lineNumber;             // 源代码行号
    QString originalText;       // 原始文本
    
    Instruction() : type(InstructionType::Other), lineNumber(0) {}
};

/**
 * @brief CPU模拟器类
 * 
 * 模拟一个简单的16位CPU，支持基本的汇编指令执行、
 * 寄存器管理、内存访问和中断处理。
 */
class CpuSimulator : public QObject
{
    Q_OBJECT

public:
    explicit CpuSimulator(QObject *parent = nullptr);
    ~CpuSimulator() override;

    // 基本控制方法
    
    /**
     * @brief 加载汇编程序
     * @param assemblyCode 汇编代码文本
     * @return bool 加载是否成功
     */
    bool loadProgram(const QString& assemblyCode);

    /**
     * @brief 开始执行程序
     * @return bool 执行是否成功开始
     */
    bool executeProgram();

    /**
     * @brief 单步执行
     * @return bool 单步执行是否成功
     */
    bool stepExecution();

    /**
     * @brief 暂停执行
     */
    void pauseExecution();

    /**
     * @brief 继续执行
     */
    void resumeExecution();

    /**
     * @brief 停止执行
     */
    void stopExecution();

    /**
     * @brief 重置CPU状态
     */
    void resetCpu();

    // 寄存器访问方法

    /**
     * @brief 获取寄存器值
     * @param registerName 寄存器名称
     * @return int 寄存器值
     */
    int getRegister(const QString& registerName) const;

    /**
     * @brief 设置寄存器值
     * @param registerName 寄存器名称
     * @param value 要设置的值
     */
    void setRegister(const QString& registerName, int value);

    /**
     * @brief 获取所有寄存器状态
     * @return QMap<QString, int> 寄存器名称到值的映射
     */
    QMap<QString, int> getAllRegisters() const;

    /**
     * @brief 获取寄存器值（内部方法，不加锁）
     * @param registerName 寄存器名称
     * @return int 寄存器值
     */
    int getRegisterInternal(const QString& registerName) const;
    
    /**
     * @brief 设置寄存器值（内部方法，不加锁）
     * @param registerName 寄存器名称
     * @param value 要设置的值
     */
    void setRegisterInternal(const QString& registerName, int value);

    // 内存访问方法

    /**
     * @brief 读取内存值
     * @param address 内存地址
     * @return int 内存值
     */
    int getMemory(int address) const;

    /**
     * @brief 写入内存值
     * @param address 内存地址
     * @param value 要写入的值
     */
    void setMemory(int address, int value);

    /**
     * @brief 批量读取内存
     * @param startAddress 起始地址
     * @param size 读取大小
     * @return QList<int> 内存值列表
     */
    QList<int> getMemoryRange(int startAddress, int size) const;

    /**
     * @brief 批量写入内存
     * @param startAddress 起始地址
     * @param values 要写入的值列表
     */
    void setMemoryRange(int startAddress, const QList<int>& values);

    // 标志位操作

    /**
     * @brief 获取标志寄存器值
     * @return int 标志寄存器值
     */
    int getFlags() const;

    /**
     * @brief 设置标志寄存器值
     * @param flags 标志值
     */
    void setFlags(int flags);

    /**
     * @brief 检查特定标志位
     * @param flag 标志位
     * @return bool 标志位是否设置
     */
    bool isFlagSet(CpuFlags flag) const;

    /**
     * @brief 设置特定标志位
     * @param flag 标志位
     * @param value 是否设置
     */
    void setFlag(CpuFlags flag, bool value);

    // 状态查询方法

    /**
     * @brief 获取CPU当前状态
     * @return CpuState CPU状态
     */
    CpuState getState() const;

    /**
     * @brief 获取当前指令指针
     * @return int 指令指针值
     */
    int getInstructionPointer() const;

    /**
     * @brief 设置指令指针
     * @param ip 新的指令指针值
     */
    void setInstructionPointer(int ip);

    /**
     * @brief 获取当前执行的指令
     * @return Instruction 当前指令
     */
    Instruction getCurrentInstruction() const;

    /**
     * @brief 检查CPU是否停机
     * @return bool 是否停机
     */
    bool isHalted() const;

    /**
     * @brief 触发中断
     * @param interruptNumber 中断号
     * @return bool 中断是否成功触发
     */
    bool triggerInterrupt(int interruptNumber);

    /**
     * @brief 设置中断管理器
     * @param manager 外部中断管理器指针
     */
    void setInterruptManager(InterruptManager* manager);

    // 程序分析方法

    /**
     * @brief 获取加载的指令列表
     * @return QList<Instruction> 指令列表
     */
    QList<Instruction> getInstructions() const;

    /**
     * @brief 获取程序大小
     * @return int 指令数量
     */
    int getProgramSize() const;

    /**
     * @brief 设置断点
     * @param lineNumber 行号
     */
    void setBreakpoint(int lineNumber);

    /**
     * @brief 清除断点
     * @param lineNumber 行号
     */
    void clearBreakpoint(int lineNumber);

    /**
     * @brief 检查是否有断点
     * @param lineNumber 行号
     * @return bool 是否有断点
     */
    bool hasBreakpoint(int lineNumber) const;

    /**
     * @brief 清除所有断点
     */
    void clearAllBreakpoints();

private:
    // 指令解析和执行

    /**
     * @brief 解析汇编代码
     * @param assemblyCode 汇编代码
     * @return bool 解析是否成功
     */
    bool parseAssemblyCode(const QString& assemblyCode);

    /**
     * @brief 解析单条指令
     * @param line 代码行
     * @param lineNumber 行号
     * @return Instruction 解析后的指令
     */
    Instruction parseInstruction(const QString& line, int lineNumber);

    /**
     * @brief 执行单条指令
     * @param instruction 要执行的指令
     * @return bool 执行是否成功
     */
    bool executeInstruction(const Instruction& instruction);

    // 具体指令实现

    /**
     * @brief 执行MOV指令
     * @param operands 操作数列表
     * @return bool 执行是否成功
     */
    bool executeMov(const QStringList& operands);

    /**
     * @brief 执行ADD指令
     * @param operands 操作数列表
     * @return bool 执行是否成功
     */
    bool executeAdd(const QStringList& operands);

    /**
     * @brief 执行SUB指令
     * @param operands 操作数列表
     * @return bool 执行是否成功
     */
    bool executeSub(const QStringList& operands);

    /**
     * @brief 执行MUL指令
     * @param operands 操作数列表
     * @return bool 执行是否成功
     */
    bool executeMul(const QStringList& operands);

    /**
     * @brief 执行DIV指令
     * @param operands 操作数列表
     * @return bool 执行是否成功
     */
    bool executeDiv(const QStringList& operands);

    /**
     * @brief 执行CMP指令
     * @param operands 操作数列表
     * @return bool 执行是否成功
     */
    bool executeCmp(const QStringList& operands);

    /**
     * @brief 执行JMP指令
     * @param operands 操作数列表
     * @return bool 执行是否成功
     */
    bool executeJmp(const QStringList& operands);

    /**
     * @brief 执行JE指令
     * @param operands 操作数列表
     * @return bool 执行是否成功
     */
    bool executeJe(const QStringList& operands);

    /**
     * @brief 执行INT指令
     * @param operands 操作数列表
     * @return bool 执行是否成功
     */
    bool executeInt(const QStringList& operands);

    /**
     * @brief 执行HLT指令
     * @param operands 操作数列表
     * @return bool 执行是否成功
     */
    bool executeHlt(const QStringList& operands);

    // 辅助方法

    /**
     * @brief 解析操作数
     * @param operand 操作数字符串
     * @return int 操作数值
     */
    int parseOperand(const QString& operand);

    /**
     * @brief 检查是否为寄存器名
     * @param name 名称
     * @return bool 是否为寄存器
     */
    bool isRegister(const QString& name) const;

    /**
     * @brief 检查是否为立即数
     * @param operand 操作数
     * @return bool 是否为立即数
     */
    bool isImmediate(const QString& operand) const;

    /**
     * @brief 检查是否为内存地址
     * @param operand 操作数
     * @return bool 是否为内存地址
     */
    bool isMemoryAddress(const QString& operand) const;

    /**
     * @brief 解析内存地址
     * @param address 地址字符串
     * @return int 内存地址
     */
    int parseMemoryAddress(const QString& address);

    /**
     * @brief 更新标志位
     * @param result 运算结果
     */
    void updateFlags(int result);

    /**
     * @brief 查找标签地址
     * @param label 标签名
     * @return int 标签对应的地址（-1表示未找到）
     */
    int findLabelAddress(const QString& label);

    /**
     * @brief 初始化寄存器
     */
    void initializeRegisters();

    /**
     * @brief 初始化内存
     */
    void initializeMemory();

private:
    // CPU状态
    CpuState currentState;
    
    // 寄存器
    QMap<QString, int> registers;
    
    // 内存
    QList<int> memory;
    
    // 程序相关
    QList<Instruction> instructions;
    QMap<QString, int> labels;
    QSet<int> breakpoints;
    
    // 执行控制
    int instructionPointer;
    bool halted;
    mutable QMutex cpuMutex;
    
    // 常量定义
    static const int MEMORY_SIZE = 65536;  // 64KB内存
    static const int STACK_BASE = 0xFFFF;  // 栈基址
    
    // 寄存器名称列表
    static const QStringList REGISTER_NAMES;

    InterruptManager* interruptManager;         // 中断管理器
    QTimer* executionTimer;                     // 执行计时器，用于非阻塞执行

signals:
    /**
     * @brief CPU状态改变信号
     * @param newState 新状态
     */
    void stateChanged(CpuState newState);

    /**
     * @brief 指令执行完成信号
     * @param instruction 执行的指令
     */
    void instructionExecuted(const Instruction& instruction);

    /**
     * @brief 寄存器值改变信号
     * @param registerName 寄存器名
     * @param newValue 新值
     */
    void registerChanged(const QString& registerName, int newValue);

    /**
     * @brief 内存值改变信号
     * @param address 内存地址
     * @param newValue 新值
     */
    void memoryChanged(int address, int newValue);

    /**
     * @brief 中断触发信号
     * @param interruptNumber 中断号
     */
    void interruptTriggered(int interruptNumber);

    /**
     * @brief 错误信号
     * @param errorMessage 错误信息
     */
    void errorOccurred(const QString& errorMessage);

    /**
     * @brief 断点命中信号
     * @param lineNumber 断点行号
     */
    void breakpointHit(int lineNumber);

private slots:
    /**
     * @brief 执行下一条指令 (计时器槽函数)
     */
    void executeNextInstruction();
};

#endif // CPUSIMULATOR_H 